package cn.ddiancan.auth.service.converter;

import java.util.HashMap;
import java.util.Map;

import cn.ddiancan.auth.service.token.XddAuth2SmsCodeAuthenticationToken;
import cn.ddiancan.auth.utils.OAuth2EndpointUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

public class XddSmsCodeAuthenticationConver implements AuthenticationConverter {

    private static final String AUTHORIZATION_TYPE = "sms_code";

    private static final String SMS_CODE = "sms_code";

    private static final String PHONE_NUMBER = "phone_number";

    private static final String REQUEST_TYPE = "request_type";

    @Override
    public Authentication convert(HttpServletRequest request) {
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
        if (!AUTHORIZATION_TYPE.equals(grantType)) {
            return null;
        }
        Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
        MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
        String smsCode = parameters.getFirst(SMS_CODE);
        String phoneNumber = parameters.getFirst(PHONE_NUMBER);
        String requestType = parameters.getFirst(REQUEST_TYPE);
        if (!StringUtils.hasText(smsCode)) {
            OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, SMS_CODE, "");
        }
        Map<String, Object> additionalParameters = new HashMap<>();
        parameters.forEach((key, value) -> {
            if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) && !key.equals(OAuth2ParameterNames.CLIENT_ID) &&
                !key.equals(AUTHORIZATION_TYPE)) {
                additionalParameters.put(key, value.get(0));
            }
        });
        return new XddAuth2SmsCodeAuthenticationToken(clientPrincipal, additionalParameters, smsCode, phoneNumber,
            requestType);
    }
}
